/* eslint-disable no-param-reassign */
/* eslint-disable @typescript-eslint/no-explicit-any */
import {
  ControlVO,
  GridController,
  GridNotifyState,
  GridRowState,
  handleAllSettled,
  IColumnState,
  MDCtrlLoadParams,
} from '@ibiz-template/runtime';
import dayjs from 'dayjs';
import { ICheckinGridState } from './i-checkin-grid.state';

/**
 * 排班表格
 *
 * @export
 * @class CheckInGridController
 * @extends {GridController}
 */
export class CheckInGridController extends GridController {
  declare state: ICheckinGridState;

  /**
   * @description 星期数组
   * @type {string[]}
   * @memberof CheckInGridController
   */
  public weekDays: string[] = ['日', '一', '二', '三', '四', '五', '六'];

  /**
   * @description 启用批操作
   * @type {boolean}
   * @memberof CheckInGridController
   */
  public enableBatch: boolean = true;

  /**
   * @description 自定义列状态
   * @type {IColumnState[]}
   * @memberof CheckInGridController
   */
  public customColumnStates: IColumnState[] = [];

  protected async onCreated(): Promise<void> {
    if (this.model.degridColumns) {
      this.model.frozenFirstColumn = this.model.degridColumns.length;
    }
    await super.onCreated();
    const { ENABLEBATCH } = this.controlParams;
    if (ENABLEBATCH) {
      this.enableBatch = ENABLEBATCH === 'true';
    }
  }

  protected initState(): void {
    super.initState();
    this.state.checkinData = [];
    this.state.queryParams = {};
    this.state.customColumns = [];
  }

  /**
   * @description 初始化月份列
   * @protected
   * @returns {*}  {Promise<void>}
   * @memberof CheckInGridController
   */
  protected async initMonthColumns(chooseMonth: string): Promise<void> {
    if (!this.model.degridColumns || !this.model.degridDataItems) {
      return;
    }
    this.state.customColumns = [];
    this.customColumnStates = [];
    let now = dayjs();
    if (chooseMonth) {
      now = dayjs(chooseMonth);
    }
    const dayCount = dayjs().daysInMonth();
    for (let i = 1; i <= dayCount; i++) {
      const targetDate = dayjs(`${now.year()}-${now.month() + 1}-${i}`);
      const targetDay = targetDate.day();
      const filedName = targetDate.format('YYYY-MM-DD');
      const column = {
        aggMode: 'NONE',
        align: 'CENTER',
        appDEFieldId: filedName,
        appId: this.model.appId,
        caption: `${i}\n${this.weekDays[targetDay]}`,
        codeName: filedName,
        columnType: 'DEFGRIDCOLUMN',
        dataItemName: filedName,
        enableSort: false,
        id: filedName,
        valueType: 'SIMPLE',
        width: 100,
        widthUnit: 'PX',
        userParam: { columnType: 'date' },
      };
      this.state.customColumns.push(column);
      this.customColumnStates.push({
        key: column.codeName!,
        caption: column.caption!,
        hidden: false,
        hideMode: 0,
        uaColumn: column.columnType === 'UAGRIDCOLUMN',
        adaptive: column.widthUnit === 'STAR',
        columnWidth: column.width,
      });
    }
    await Promise.all(
      this.state.customColumns.map(async column =>
        this.initColumnsController(column),
      ),
    );
  }

  async getFetchParams(extraParams?: IParams): Promise<IParams> {
    const resultParams = await super.getFetchParams(extraParams);
    this.state.isLoaded = false;
    await this.initMonthColumns(resultParams.choose_month);
    this.state.queryParams = resultParams;
    return resultParams;
  }

  async afterLoad(
    args: MDCtrlLoadParams,
    items: ControlVO[],
  ): Promise<ControlVO[]> {
    // 每次表格刷新时通知表格属性列,加载代码表,避免动态代码表更新不及时
    await handleAllSettled(
      Object.values(this.fieldColumns).map(async fieldColumn => {
        await fieldColumn.loadCodeList();
      }),
      false,
    );

    const dayItems = this.calcDayData(items);
    // 生成表格row对象
    const rows = dayItems.map(item => {
      const row = new GridRowState(item, this);
      this.gridStateNotify(row, GridNotifyState.LOAD);
      return row;
    });

    if (args.isLoadMore) {
      this.state.rows.push(...rows);
    } else {
      this.state.rows = rows;
    }

    // 响应式写法，用state里遍历出来的row才是reactive
    await this.updateRows(this.state.rows);

    this.calcGroupData(dayItems);
    await this.loadRemoteAgg();
    this.calcAggResult(dayItems);

    this.calcShowMode(dayItems);
    this.calcTotalData();

    return items;
  }

  /**
   * @description 计算日期数据
   * @protected
   * @param {ControlVO[]} items
   * @returns {*}  {IData[]}
   * @memberof CheckInGridController
   */
  protected calcDayData(items: ControlVO[]): ControlVO[] {
    const result: ControlVO[] = [];
    items.forEach(item => {
      const index = result.findIndex(
        resultItem => resultItem.member_id === item.member_id,
      );
      if (index === -1) {
        item.children = {
          [item.checkin_date]: { ...item },
        };
        result.push(item);
      } else {
        result[index].children[item.checkin_date] = item;
      }
    });
    return result;
  }

  public setBatchCheckInData(columnName: string, item: IData): void {
    this.state.rows.forEach(row => {
      const { children } = row.data;
      const data = children[columnName];
      if (data) {
        const { id } = data;
        this.setCheckInData(id, { ...item, id });
      }
    });
  }

  public setCheckInData(id: string, item: IData): void {
    const index = this.state.checkinData.findIndex(data => data.id === id);
    if (index === -1) {
      this.state.checkinData.push(item);
    } else {
      this.state.checkinData[index] = item;
    }
  }

  public removeCheckInData(id: string): void {
    const index = this.state.checkinData.findIndex(data => data.id === id);
    if (index !== -1) {
      this.state.checkinData.splice(index, 1);
    }
  }

  public batchRemoveCheckInData(columnName: string): void {
    this.state.rows.forEach(row => {
      const { children } = row.data;
      const data = children[columnName];
      if (data) {
        this.removeCheckInData(data.id);
      }
    });
  }

  public clearCheckInData(): void {
    this.state.checkinData = [];
  }

  public async saveCheckInData(): Promise<void> {
    const app = ibiz.hub.getApp(this.context.srfappid);
    const result = await app.net.post(
      `/${this.dataEntity.codeName2}/manual`,
      this.state.checkinData,
    );
    if (result.ok) {
      this.state.isLoaded = false;
      this.state.checkinData = [];
      this.load();
    }
  }
}
